package service

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"lot_admin_api/api"
	"lot_admin_api/internal/consts"
	"lot_admin_api/internal/dao"
	"lot_admin_api/internal/model"
	GenInt64Id "lot_admin_api/utility/genInt64IdOfString"
	"lot_admin_api/utility/paging"
	"lot_admin_api/utility/response"
)

type sBilling struct {
}

var insBilling = sBilling{}

func Billing() *sBilling {
	return &insBilling
}

// AddBilling 添加计费方案
func (s *sBilling) AddBilling(ctx context.Context, req *api.AddBillingReq) (lastInsertId string, err error) {
	r := g.RequestFromCtx(ctx)
	var billingInfo *model.BillingDbInfoRes
	_ = gconv.Scan(req, &billingInfo)
	billingInfo.Id = GenInt64Id.GenInt64IdOfString() // 生成雪花id
	// 将收费方案id 放置到每一个详情数据里面
	for _, value := range billingInfo.BillingDetails {
		value.BillingId = billingInfo.Id
		value.Id = GenInt64Id.GenInt64IdOfString() // 生成雪花id
	}
	// 事务
	err = dao.LotBillingScheme.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) (err error) {
		// 保存计费方案
		if _, err := dao.LotBillingScheme.Ctx(ctx).OmitEmpty().Save(billingInfo); err != nil {
			response.JsonExit(r, consts.HTTPInternalServer.Code(), "保存数据失败")
		}
		// 当有详情参数时对详情进行操作
		if req.BillingDetails != nil && len(req.BillingDetails) > 0 {
			// 保存计费方案的详情
			if _, err := dao.LotBillingDetails.Ctx(ctx).Insert(billingInfo.BillingDetails); err != nil {
				response.JsonExit(r, consts.HTTPInternalServer.Code(), "保存详情数据失败")
			}
		}
		return err
	})
	return billingInfo.Id, err
}

// EditBilling 编辑计费方案
func (s *sBilling) EditBilling(ctx context.Context, req *api.EditBillingReq) (lastInsertId string, err error) {
	r := g.RequestFromCtx(ctx)
	var billingInfo *model.BillingDetailRes
	_ = gconv.Scan(req, &billingInfo)
	// 将收费方案id 放置到每一个详情数据里面
	for _, value := range billingInfo.BillingDetails {
		value.BillingId = billingInfo.Id
		value.Id = GenInt64Id.GenInt64IdOfString() // 生成雪花id
	}
	// 查询有没有该计费方案
	_, err = s.SearchBilling(ctx, billingInfo.Id)
	// 事务
	err = dao.LotBillingScheme.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) (err error) {
		// 更新计费方案表
		if _, err := dao.LotBillingScheme.Ctx(ctx).OmitEmpty().Where("id", billingInfo.Id).Update(billingInfo); err != nil {
			response.JsonExit(r, consts.HTTPInternalServer.Code(), "保存数据失败")
		}
		// 当有详情参数时对详情进行操作
		if req.BillingDetails != nil && len(req.BillingDetails) > 0 {
			// 删除当前计费方案下所有的详情
			if _, err := dao.LotBillingDetails.Ctx(ctx).Where("billing_id", billingInfo.Id).Delete(); err != nil {
				response.JsonExit(r, consts.HTTPInternalServer.Code(), "删除详情失败")
			}
			// 重新插入详情
			if _, err := dao.LotBillingDetails.Ctx(ctx).OmitEmpty().Insert(billingInfo.BillingDetails); err != nil {
				response.JsonExit(r, consts.HTTPInternalServer.Code(), "保存详情数据失败")
			}
		}
		return err
	})
	return billingInfo.Id, err
}

// DeleteBilling 删除计费方案
func (s *sBilling) DeleteBilling(ctx context.Context, req *api.DeleteBillingReq) (res string, err error) {
	r := g.RequestFromCtx(ctx)
	// 查询有没有该计费方案
	_, err = s.SearchBilling(ctx, req.Id)
	// 事务
	err = dao.LotBillingScheme.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) (err error) {
		// 更新计费方案表
		if _, err := dao.LotBillingScheme.Ctx(ctx).Where("id", req.Id).Delete(); err != nil {
			response.JsonExit(r, consts.HTTPInternalServer.Code(), "保存数据失败")
		}
		// 删除当前计费方案下所有的详情
		if _, err := dao.LotBillingDetails.Ctx(ctx).Where("billing_id", req.Id).Delete(); err != nil {
			response.JsonExit(r, consts.HTTPInternalServer.Code(), "删除详情失败")
		}
		return err
	})
	return req.Id, err
}

// SearchBilling 搜索计费方案
func (s *sBilling) SearchBilling(ctx context.Context, id string) (findOne *model.BillingDbInfoRes, err error) {
	r := g.RequestFromCtx(ctx)
	searchInfo := g.Map{
		"id": id,
	}
	if err = dao.LotBillingScheme.Ctx(ctx).WithAll().Where(searchInfo).Scan(&findOne); err != nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "没有查询到计费方案")
	}
	return findOne, err
}

// BillingList 获取收费方案列表
func (s *sBilling) BillingList(ctx context.Context, req *api.BillingListReq) (res *model.BillingListRes, err error) {
	r := g.RequestFromCtx(ctx)
	var BillingDbListReq = make([]*model.BillingDbInfoRes, 0)
	// 获取分页偏移量
	startNum, endNum := paging.Paging(req.Paging)
	searchInfo := g.Map{
		"billing_name like ?":                  "%" + req.BillingName + "%",
		"billing_type":                         req.BillingType,
		"company_id = ? OR company_id IS NUll": req.CompanyId,
	}
	if err = dao.LotBillingScheme.Ctx(ctx).WithAll().OmitEmpty().Where(searchInfo).Limit(startNum, endNum).Scan(&BillingDbListReq); err != nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "查找收费方案列表失败")
	}
	countInfo, err := dao.LotBillingScheme.Ctx(ctx).OmitEmpty().Where(searchInfo).Count()
	putCount := paging.PutCount(req.Paging, countInfo)
	res = &model.BillingListRes{
		List:    BillingDbListReq,
		PutPage: *putCount,
	}
	return res, err
}
